//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.Provenance.Controls.Presenter
{
    using System.Collections.ObjectModel;
    using System.Windows;
    using Microsoft.Research.Provenance.Controls.View;
    using Microsoft.Research.Provenance.ProvenanceDataService;
    using Microsoft.Research.ProvenanceInterfaces;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.Monitor;
    using System.ComponentModel;
    using Microsoft.Practices.Unity;
    using System;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using Microsoft.Research.ScientificWorkflow.TridentModel;
    using System.Text;

    public class ActivityDataProductPresenter : IProvenancePresenter, INotifyPropertyChanged , IDisposable
    {
        /// <summary>
        /// Holds the UnityContainer
        /// </summary>
        private IUnityContainer container;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="view">The view associated with the presenter.</param>
        public ActivityDataProductPresenter(IUnityContainer container, ActivityDataProductView view)
        {
            this.View = view;
            this.container = container;

            this.ActivityDataProducts = new ObservableCollection<DataProductItem>();

            view.Model = this;
        }

        /// <summary>
        /// List of data products for the selected activity.
        /// </summary>
        public ObservableCollection<DataProductItem> ActivityDataProducts { get; private set; }

        /// <summary>
        /// The control which displays the dataproducts
        /// </summary>
        public UIElement View { get; set; }

        /// <summary>
        /// Activity label.
        /// </summary>
        private string activityLabel;

        /// <summary>
        /// Activity label.
        /// </summary>
        public string ActivityLabel
        {
            get
            {
                return this.activityLabel;
            }
            private set
            {
                this.activityLabel = value;
                this.OnNotifyPropertyChanged("ActivityLabel");
            }
        }

        /// <summary>
        /// Inidicates whether data is not present.
        /// </summary>
        private bool doesNotContainItems;

        /// <summary>
        /// Gets whether data is not present.
        /// </summary>
        public bool DoesNotContainItems
        {
            get
            {
                return this.doesNotContainItems;
            }
            private set
            {
                this.doesNotContainItems = value;
                this.OnNotifyPropertyChanged("DoesNotContainItems");
            }
        }

        /// <summary>
        /// Inidicates whether data is present.
        /// </summary>
        private bool containItems;

        /// <summary>
        /// Gets whether data is present.
        /// </summary>
        public bool ContainItems
        {
            get
            {
                return this.containItems;
            }
            private set
            {
                this.containItems = value;
                this.DoesNotContainItems = !this.ContainItems;
                this.OnNotifyPropertyChanged("ContainItems");
            }
        }

        /// <summary>
        /// BreadCrumb text binded with UI.
        /// </summary>
        private StringBuilder breadcrumb;

        /// <summary>
        /// Gets or sets the Breadcrumb property, binded with UI.
        /// </summary>
        public string Breadcrumb
        {
            get
            {
                return this.breadcrumb.ToString();
            }
            set
            {
                this.breadcrumb = new StringBuilder();
                this.breadcrumb.Append(value);

                // Don't display breadcrumb if not applicable.
                if (string.IsNullOrEmpty(this.Breadcrumb))
                    IsBreadcrumbNull = false;
                else
                    IsBreadcrumbNull = true;

                this.OnNotifyPropertyChanged("Breadcrumb");
            }
        }

        /// <summary>
        /// Inidicates whether breadcrumb text is not present.
        /// </summary>
        private bool isBreadcrumbNull;

        /// <summary>
        /// Gets or sets a value indicating whether breadcrumb is null.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if breadcrumb is null; otherwise, <c>false</c>.
        /// </value>
        public bool IsBreadcrumbNull
        {
            get
            {
                return this.isBreadcrumbNull;
            }
            private set
            {
                this.isBreadcrumbNull = value;
                this.OnNotifyPropertyChanged("IsBreadcrumbNull");
            }
        }

        #region IProvenancePresenter Members

        /// <summary>
        /// Display the view of the presenter and retrieve the data products.
        /// </summary>
        /// <param name="compositeModel">The activity for which the data products are to be retrieved.</param>
        public void Show(BaseModel model)
        {
            this.ActivityDataProducts.Clear();
            this.ActivityLabel = model.Name;
            string breadcrumb = string.Empty;

            try
            {
                Collection<DataProductItem> registryDataProducts = this.container.Resolve<DataRetriever>().GetDataProducts(model, ref breadcrumb);
                if (registryDataProducts != null)
                {
                    foreach (DataProductItem dataproduct in registryDataProducts)
                    {
                        this.ActivityDataProducts.Add(dataproduct);
                    }
                }

                this.Breadcrumb = breadcrumb;

                // This is to set the visibility of the data products control.
                this.ContainItems = this.ActivityDataProducts.Count > 0;

                this.View.Visibility = Visibility.Visible;
            } 
            catch (TridentCustomException ex)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(ex);
            }
            catch (Exception exp)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(exp);
            }
        }

        /// <summary>
        /// Hide the view.
        /// </summary>
        public void Hide()
        {
            this.ActivityDataProducts.Clear();
            this.View.Visibility = Visibility.Collapsed;
        }

        #endregion

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Event for property change.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raise property changed eventargs.
        /// </summary>
        /// <param name="changeProperty">Property anme.</param>
        private void OnNotifyPropertyChanged(string changeProperty)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(changeProperty));
            }
        }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// Clears the collection and View Object
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// nullify and Disposes the object 
        /// </summary>
        /// <param name="disposing"></param>
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                this.container.Dispose();
                this.View = null;
            }
        }

        #endregion
    }
}
